﻿using NUnit.Framework;
using Sessionizer.Core;
using Sessionizer.Tests.Abstraction;

namespace Sessionizer.Tests.Core
{
   
    public abstract class ResolutionTests : AbstractTest
    {
        protected override void FixtureConfigure(IIoCContainerBuilder container)
        {
            base.FixtureConfigure(container);
            container.RegisterType<IInterface1, Interface1Implementation>();
            container.RegisterType<IInterface2, Interface2Implementation>();
        }

        private class Class1 : IInterface1
        {
            public Class1(IInterface2 i1)
            {
            }
        }

        private class Class2
        {
            public Class2(ISessions<IInterface2> i1)
            {
            }
        }

        private interface IInterface1
        {
        }

        private interface IInterface2
        {
        }

        private interface IInterface3
        {
        }

        private class Interface1Implementation : IInterface1
        {
        }

        private class Interface2Implementation : IInterface2
        {
        }


        private class Interface3Implementation : IInterface3
        {
        }

        [Test]
        public void CommonResolutionWorksInsideSession()
        {
            using (ISession session = Container.Session())
            {
                using (session.Bind())
                {
                    Container.Resolve<Class2>();
                }
            }
        }

        [Test]
        public void GenericInstancesResolves()
        {
            using (ISession session = Container.Session())
            {
                using (session.Bind())
                {
                    var i11 = Container.Resolve<ISessions<IInterface1>>();
                    var i21 = Container.Resolve<ISessions<IInterface2>>();
                    var i12 = Container.Resolve<ISessions<IInterface1>>();
                    var i22 = Container.Resolve<ISessions<IInterface2>>();
                    Assert.IsTrue(ReferenceEquals(i11.Instance, i12.Instance));
                    Assert.IsTrue(ReferenceEquals(i21.Instance, i22.Instance));
                }
            }
        }

        [Test]
        public void GettingSessionsDataViaSessionMethodsWorks()
        {
            using (ISession session = Container.Session())
            {
                IInterface3 i3 = new Interface3Implementation();
                using (session.Bind())
                {
                    session.Set(i3);
                    var i33 = Container.Resolve<ISessions<IInterface3>>();
                    Assert.IsTrue(ReferenceEquals(i3, i33.Instance));
                }
                var i32 = session.Get<IInterface3>();
                Assert.IsTrue(ReferenceEquals(i3, i32));
            }
        }

        [Test]
        public void ResolutionWorksAndWeDoNotBrokeContainer()
        {
            Container.Resolve<Class1>();
        }

        [Test]
        public void SetingSessionsDataViaSessionMethodsWorks()
        {
            using (ISession session = Container.Session())
            {
                IInterface3 i3 = new Interface3Implementation();
                session.Set(i3);
                using (session.Bind())
                {
                    var i33 = Container.Resolve<ISessions<IInterface3>>();
                    Assert.IsTrue(ReferenceEquals(i3, i33.Instance));
                }
            }
        }


        [Test]
        public void SetingSessionsDataWorks()
        {
            using (ISession session = Container.Session())
            {
                IInterface3 i3 = new Interface3Implementation();
                session.Set(i3);
                var i32 = session.Get<ISessions<IInterface3>>();
                using (session.Bind())
                {

                    
                    var i33 = Container.Resolve<ISessions<IInterface3>>();

                    Assert.IsTrue(ReferenceEquals(i3, i32.Instance));
                    Assert.IsTrue(ReferenceEquals(i3, i33.Instance));
                }
            }
        }
    }
}